﻿#region Copyright(C) 2009 NCS Pte. Ltd. All rights reserved.
// ==================================================================================================
// Copyright(C) 2006 NCS Pte. Ltd. All rights reserved.
//
// SYSTEM NAME	:   iConnect .Net Application Framework
// COMPONENT ID :   NCS.IConnect.ExceptionHandling.Wcf
// COMPONENT DESC:  
//
// CREATED DATE/BY:  22 Desc 2009 / Jiang Jin Nan
//
// REVISION HISTORY:	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================
#endregion

using CBEC.Core;
using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace CBEC.Core.Wcf
{
    /// <summary>
    /// The Extended <see cref="ServiceHost"/> to automatically add <see cref="ServiceExceptionDetail"/> fault description.
    /// </summary>
    public class ExceptionHandlingServiceHost:ServiceHost
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ExceptionHandlingServiceHost"/> class.
        /// </summary>
        /// <param name="singletonInstance">The instance of the hosted service.</param>
        /// <param name="baseAddresses">An <see cref="T:System.Array"/> of type <see cref="T:System.Uri"/> that contains the base addresses for the hosted service.</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="singletonInstance"/> is null.</exception>
        public ExceptionHandlingServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        { }

        /// <summary>
        /// Initializes a new instance of the <see cref="ExceptionHandlingServiceHost"/> class.
        /// </summary>
        /// <param name="serviceType">Type of the service.</param>
        /// <param name="baseAddresses">The base addresses.</param>
        public ExceptionHandlingServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        { }

        /// <summary>
        /// Invoked during the transition of a communication object into the opening state.
        /// </summary>
        protected override void OnOpening()
        {
            base.OnOpening();
            foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
            {
                foreach (OperationDescription operation in endpoint.Contract.Operations)
                {
                    if (!FaultDescriptionExists(operation, typeof(ServiceExceptionDetail)))
                    {
                        string action = ServiceExceptionDetail.GetFaultAction(endpoint.Contract.Namespace, operation.Name);
                        FaultDescription faultDescription = new FaultDescription(action);
                        faultDescription.DetailType = typeof(ServiceExceptionDetail); 
                        faultDescription.Name = "ServiceExceptionDetailFault";
                        operation.Faults.Add(faultDescription);
                    }

                    if (!FaultDescriptionExists(operation, typeof(ValidationFault)))
                    {
                        string action = ValidationFault.GetFaultAction(endpoint.Contract.Namespace, operation.Name);
                        FaultDescription faultDescription = new FaultDescription(action);
                        faultDescription.DetailType = typeof(ValidationFault);
                        faultDescription.Name = "ValidationFault";
                        operation.Faults.Add(faultDescription);
                    }   
                }
            }
        }

        private static bool FaultDescriptionExists(OperationDescription operation, Type faultType)
        {
            foreach (var fault in operation.Faults)
            {
                if (fault.DetailType == faultType)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
